package com.xy.tool.util;

import com.xy.lang.util.CalendarUtils;
import com.xy.tool.report.excel.ExcelTemplate;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * excel相关工具
 * 
 * @author zsp
 *
 */
public class ExcelUtils {
	
	/**
	 * excel最大导出行数
	 */
	public final static int MAX_EXPORT_ROWS = 1000;
	
	private static final Logger logger = LoggerFactory.getLogger(ExcelUtils.class);

	public static void renderAlertMessageByExcel(HttpServletResponse response, String message) {
		try {
			try (SXSSFWorkbook workbook = ExcelTemplate.createAlertMessage(message)) {
				try (ServletOutputStream out = response.getOutputStream()) {
					workbook.write(out);
				}
			}
		} catch (IOException ioe) {
			logger.error(ioe.getMessage(), ioe);
		}
	}
	
	/**
	 * 构建HttpServletResponse
	 * 
	 * @param response
	 * @param name
	 */
	public static void buildResponse(HttpServletResponse response, String name) {
		if(response == null) {
			throw new IllegalArgumentException();
		}
		String fileName = String.format("%s%s.xlsx", name, CalendarUtils.format(LocalDateTime.now(), "yyyyMMddHHmmss"));
		response.setContentType("application/x-msdownload");
		try {
			response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
		} catch (UnsupportedEncodingException e) {
			logger.error("构建HttpServletResponse异常", e);
		}
	}
	
	/**
	 * 构建HttpServletResponse
	 * 
	 * @param response
	 */
	public static void buildResponse(HttpServletResponse response) {
		buildResponse(response, "");
	}
	
	/**
	 * 通过标题、字段、数据来构建一个excel文档
	 * 
	 * @param headers 标题
	 * @param columns 字段
	 * @param list 数据集
	 * @return 返回一个一个excel文档
	 */
	public static <T> XSSFWorkbook buildWorkbook(String[] headers, 
			String[] columns, 
			List<T> list) {
		if(headers == null || columns == null 
				|| headers.length == 0 || headers.length != columns.length) {
			throw new IllegalArgumentException();
		}
		XSSFWorkbook workbook = new XSSFWorkbook();
		XSSFSheet sheet1 = workbook.createSheet("Sheet1");
		// 表头
		XSSFRow hrow = sheet1.createRow(0);
		int cellIndex = 0;
		for (String header : headers) {
			XSSFCell cell = hrow.createCell(cellIndex);
			cell.setCellType(CellType.STRING);
			cell.setCellValue(header);
			cellIndex++;
		}
		if(list != null && list.size() > 0) {
			// 内容
			for (int i = 0, len = list.size(); i < len; i++) {
				XSSFRow row = sheet1.createRow(i + 1);
				T item = list.get(i);
				Class<?> clasz = item.getClass();
				cellIndex = 0;
				for (String column : columns) {
					Object result = getValue(clasz, column, item);
					XSSFCell cell = row.createCell(cellIndex);
					String cellValue = "";
					if (result == null) {
						cellValue = "";
					} else if (result instanceof Date) {
						Date d = (Date) result;
						cellValue = CalendarUtils.format(LocalDateTime.now(), "yyyyMMddHHmmss");
					} else {
						cell.setCellType(CellType.STRING);
						cellValue = result.toString();
					}
					cell.setCellValue(cellValue);
					cellIndex++;
				}
			}
		}
		
		return workbook;
	}
	/**
	 * 通过标题、字段、数据来构建一个excel文档
	 *
	 * @param headers 标题
	 * @param columns 字段
	 * @param list 数据集
	 * @return 返回一个一个excel文档
	 */
	public static <T> XSSFWorkbook buildWorkbooks(String[] headers,
												 String[] columns,
												 List<Map<String,Object>> list) {
		if(headers == null || columns == null
				|| headers.length == 0 || headers.length != columns.length) {
			throw new IllegalArgumentException();
		}
		XSSFWorkbook workbook = new XSSFWorkbook();
		XSSFSheet sheet1 = workbook.createSheet("Sheet1");
		// 表头
		XSSFRow hrow = sheet1.createRow(0);
		int cellIndex = 0;
		for (String header : headers) {
			XSSFCell cell = hrow.createCell(cellIndex);
			cell.setCellType(CellType.STRING);
			cell.setCellValue(header);
			cellIndex++;
		}
		if(list != null && list.size() > 0) {
			// 内容
			for (int i = 0, len = list.size(); i < len; i++) {
				XSSFRow row = sheet1.createRow(i + 1);
				Map<String,Object> item = list.get(i);
				cellIndex = 0;
				for (String column : columns) {
					Object result = item.get(column);
					XSSFCell cell = row.createCell(cellIndex);
					String cellValue = "";
					if (result == null) {
						cellValue = "";
					} else if (result instanceof Date) {
						Date d = (Date) result;
						cellValue = CalendarUtils.format(LocalDateTime.now(), "yyyyMMddHHmmss");
					} else {
						cell.setCellType(CellType.STRING);
						cellValue = result.toString();
					}
					cell.setCellValue(cellValue);
					cellIndex++;
				}
			}
		}

		return workbook;
	}

	private static <T> Object getValue(Class<?> clasz, String column, T item) {
		Method method;
		try {
			method = clasz.getMethod("get" + StringUtils.capitalize(column));
			return method.invoke(item);
		} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
			logger.error(LogUtils.message("获取字段值失败", 
					new Object[] {clasz, column, item}), e);
		}
		return null;
	}

}
